package com.hotline.communication.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hotline.communication.annotation.TokenValidate;
import com.hotline.communication.constant.Constants;
import com.hotline.communication.constants.DateConstant;
import com.hotline.communication.dto.*;
import com.hotline.communication.entity.ManageTaxpayer;
import com.hotline.communication.enums.*;
import com.hotline.communication.mapper.ManageTaxpayerMapper;
import com.hotline.communication.service.*;
import com.hotline.communication.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.hotline.communication.enums.ScenarioTypeEnum.TRANSFER_TO_EXTERNAL_LINE;
import static com.hotline.communication.util.StringUtils.null2String;
import static com.hotline.communication.util.StringUtils.string2Int;

@Controller
@RequestMapping("/ivrcomm")
@Slf4j
public class IVRCommunicationFreeswitchController {

    //按键值为空的默认值
    private static final String IVR_DEFAULT_KEY_VALUE = "99";

    private static Integer VIP_NUM = 10;

    private static final String NULL = "null";

    private static final String EMPTY = "";

    @Autowired
    private WorkTimeService workTimeService;

    @Autowired
    private HolidayService holidayService;

    @Autowired
    private AppInfoService appInfoService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CallLogService callLogService;

    @Autowired
    private RecordLogService recordLogService;

    @Autowired
    private BlackInfoService blackInfoService;

    @Autowired
    private OrderSeqService orderSeqService;

    @Autowired
    private DutyUserCallService dutyUserCallService;

    @Autowired
    private CallOperationDetailService callOperationDetailService;

    @Autowired
    private DutyUserService dutyUserService;

    @Autowired
    private OrgService orgService;

    @Autowired
    private ParamSetService paramSetService;

    @Autowired
    private SatisfactionService satisfactionService;

    @Autowired
    private PlayRecordService playRecordService;

    @Autowired
    private MobileFromService mobileFromService;

    @Autowired
    private IvrService ivrService;

    @Autowired
    private ManageTaxpayerService manageTaxpayerService;


    @ResponseBody
    @RequestMapping("/getIVRToken/json")
    public JSONObject getIVRToken(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        log.info("获取token参数请求参数:{}",ivrCommunicationDTO);
        JSONObject result = new JSONObject();
        AppInfoDTO appInfoDTO = appInfoService.selectById(ivrCommunicationDTO.getAppID());
        if(Objects.isNull(appInfoDTO)) {
            log.info("验证appId:{}",result);
            return result;
        }
        if(!StringUtils.equals(ivrCommunicationDTO.getAppSecret(),appInfoDTO.getAppSecret())){
            log.info("验证appSecret:{}",result);
            return result;
        }
        //获取
        String tokenStr = stringRedisTemplate.opsForValue().get("appToken:"+appInfoDTO.getAppId());
        TokenDTO tokenDTO = null;
        if(StringUtils.isNotBlank(tokenStr)){
            tokenDTO=JSON.parseObject(tokenStr, TokenDTO.class);
        }
        if(Objects.isNull(tokenDTO)){
            tokenDTO = new TokenDTO();
            BeanUtils.copyProperties(ivrCommunicationDTO,tokenDTO);
            tokenDTO.setAppToken(UUIDUtils.getUUID());
        }
        //保存token
        stringRedisTemplate.opsForValue().set("appToken:"+appInfoDTO.getAppId(), JSON.toJSONString(tokenDTO) ,60*12, TimeUnit.MINUTES);
        result.put("appToken",tokenDTO.getAppToken());
        return result;
    }

    /**
     * 判断是否工作时间
     * @param ivrCommunicationDTO
     * @return
     */
    @ResponseBody
    @RequestMapping("/workTimeQuery/json")
    @TokenValidate
    public JSONObject workTime(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        log.info("工作时间参数请求参数:{}",ivrCommunicationDTO);
        //默认是工作时间
        JSONObject result = new JSONObject();
        result.put("isWorkTime","1");//工作时间
        String unitCode = UnitCodeUtil.getUnitCode(ivrCommunicationDTO.getAreaCode());
        //查询是否节假日
        String today = DateUtils.format(new Date(),"yyyy-M-d");
        Integer holidayCount = holidayService.count(unitCode,today);
        //是节假日，返回非工作时间
        if(holidayCount != null && holidayCount >= 1){
            result.put("isWorkTime","0");
            log.info("判断是否工作时间结果返回:{}",result);
            return result;
        }
        //查询是否工作时间
        Integer workTimeCount = workTimeService.count(unitCode);
        //非工作时间
        if(workTimeCount == null || workTimeCount == 0){
            result.put("isWorkTime","0");
            log.info("判断是否工作时间结果返回:{}",result);
            return result;
        }
        result.put("appToken",ivrCommunicationDTO.getAppToken());
        log.info("判断是否工作时间结果返回:{}",result);
        return result;
    }


    /**
     * 来电人画像(黑白名单)
     * @param ivrCommunicationDTO
     * @return
     */
    @ResponseBody
    @RequestMapping("/callerInfo/json")
    @TokenValidate
    public JSONObject callerInfo(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        log.info("来电人画像参数请求参数:{}",ivrCommunicationDTO);
        //默认是工作时间
        JSONObject result = new JSONObject();

        result.put("callerLevel","1");//用户级别 0:灰名单 1:普通用户 >1:VIP -1:黑名单  vip 23456789级，越高越优先

        String unitCode = ivrCommunicationDTO.getAreaCode();
        //是否启用AI
        String AIEnable = paramSetService.getParamValue(ParamEnum.TX_AI_ENABLE.getCode(),unitCode);
        Boolean transAI = Boolean.FALSE;
        if(!AIStatusEnum.CLOSE.getCode().equals(AIEnable)){
            transAI = Boolean.TRUE;
        }

        String callerData = "";
        //启用AI场景,设置智能场景
        if(transAI){
            callerData = getCallDataAI(AIEnable,unitCode,EMPTY);
            result.put("callerData",callerData);
        }else{
            result.put("callerData",callerData);
        }

        String caller = ivrCommunicationDTO.getCaller();
        if(StringUtils.isBlank(caller)){
            caller = EMPTY;
        }
        BlackInfoDTO blackInfoDTO = blackInfoService.selectByPhoneNumberAndOrgId(caller, unitCode);
        if(Objects.nonNull(blackInfoDTO)){
            CallerLevelEnum callerLevelEnum = CallerLevelEnum.getCallerLevelEnum(blackInfoDTO.getCallerLevel());
            if(Objects.nonNull(callerLevelEnum)){
                callerData = "";
                //VIP6
                switch (callerLevelEnum){
                    case BLACK:
                        result.put("callerLevel",String.valueOf(callerLevelEnum.getCode()));
                        break;
                    case GREY:
                        result.put("callerLevel",String.valueOf(callerLevelEnum.getCode()));
                        break;
                    case WHITE:
                        if(Objects.isNull(blackInfoDTO.getVipLevel())){
                            result.put("callerLevel",String.valueOf(VipLevelEnum.LEVEL_1.getCode() * VIP_NUM));
                        }else{
                            result.put("callerLevel",String.valueOf(blackInfoDTO.getVipLevel() * VIP_NUM));
                        }
                        break;
                    case VIP:
                        result.put("callerLevel","98");
                        callerData = blackInfoDTO.getCallData();
                        break;
                    case SPECIAL:
                        result.put("callerLevel","99");
                        callerData = blackInfoDTO.getCallData();
                        break;
                }
                result.put("callerData",callerData);
            }
            //启用AI场景,且黑白名单设置了进入AI场景
            if(transAI && WhetherEnum.YES.getCode().equals(blackInfoDTO.getIsAiEnable())){
                callerData = getCallDataAI(AIEnable,unitCode,callerData);
                result.put("callerData",callerData);
            }
        }else{
            //外地号码是否优先接听
            String longDistanceCallPrior = paramSetService.getParamValue(ParamEnum.TX_LONG_DISTANCE_CALL_PRIOR.getCode(),unitCode);
            if(StringUtils.isNotBlank(longDistanceCallPrior) &&
                    WhetherEnum.YES.getCode().equals(Integer.valueOf(longDistanceCallPrior))){
                //0开头为外地号码
                if(caller.startsWith("0")){
                    result.put("callerLevel","9");
                }
                //手机号码
                else if(caller.startsWith("1") && caller.length() == 11){
                    String phoneAreaCode = paramSetService.getParamValue(ParamEnum.TX_PHONE_AREA_CODE.getCode(),unitCode);
                    String mobileSeg = caller.substring(0,7);
                    MobileFromDTO mobileFromDTO = mobileFromService.selectById(mobileSeg);
                    if(Objects.nonNull(mobileFromDTO) &&
                            StringUtils.isNotBlank(mobileFromDTO.getAreaCode()) &&
                            !mobileFromDTO.getAreaCode().equals(phoneAreaCode)){
                        result.put("callerLevel","9");
                    }
                }

            }
        }

        //区域编码查询
        ManageTaxpayerDTO manageTaxpayerDTO = new ManageTaxpayerDTO();
        manageTaxpayerDTO.setPhoneNumber(caller);
        List<ManageTaxpayer> manageTaxpayers = manageTaxpayerService.selectByPhoneNumber(manageTaxpayerDTO);
        if(Objects.nonNull(manageTaxpayers)&&!manageTaxpayers.isEmpty()){
            result.put("areaCodeOut",manageTaxpayers.get(0).getOrgId());
        }else {
            manageTaxpayerDTO.setPhoneNumber(ivrCommunicationDTO.getCallee());
            manageTaxpayers = manageTaxpayerService.selectByPhoneNumber(manageTaxpayerDTO);
            if(Objects.nonNull(manageTaxpayers)&&!manageTaxpayers.isEmpty()) {
                result.put("areaCodeOut", manageTaxpayers.get(0).getOrgId());
            }
        }
        log.info("来电人画像结果返回:{}",result);
        return result;
    }

    /**
     * 通讯日志
     * @param ivrCommunicationDTO
     * @return
     */
    @ResponseBody
    @RequestMapping("/calllog/json")
    @TokenValidate
    public JSONObject callLogJson(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        log.info("通讯日志请求参数:{}",ivrCommunicationDTO);
        //默认为普通用户
        JSONObject result = new JSONObject();
        //设置参数
        CallLogDTO callLogDTO=new CallLogDTO();
        callLogDTO.setCallId(ivrCommunicationDTO.getCallID());
        Date nowDate=new Date();
        //场景类型
        String sceneTypeStr = null2String(ivrCommunicationDTO.getSceneType());
        Integer sceneType = string2Int(sceneTypeStr);
        ScenarioTypeEnum scenarioTypeEnum = ScenarioTypeEnum.getScenarioTypeEnum(sceneType);

        //拓展字段
        String reserveData = null2String(ivrCommunicationDTO.getReserveData());

        if(Objects.nonNull(scenarioTypeEnum)) {
            switch (scenarioTypeEnum) {
                //进IVR
                case ENTER_IVR:{
                    //呼入类型 1:呼入 2:呼出   设置呼叫号码  被叫号码
                    if(StringUtils.equals(ivrCommunicationDTO.getCallType(),"0")) {
                        callLogDTO.setCallerNo(ivrCommunicationDTO.getCaller());
                        callLogDTO.setCalledNo(ivrCommunicationDTO.getCallee());
                    }else{
                        callLogDTO.setCallerNo(ivrCommunicationDTO.getDialCaller());
                        callLogDTO.setCalledNo(ivrCommunicationDTO.getDialCallee());
                    }
                    //机构号码
                    callLogDTO.setUnitCode(ivrCommunicationDTO.getAreaCode());
                    //设置时间
                    callLogDTO.setIvrKeyTrace(ivrCommunicationDTO.getTrack());

                    //排队次数
                    int queueTimes = 1;
                    if(StringUtils.isNotBlank(ivrCommunicationDTO.getQueueTimes())
                            && !NULL.equals(ivrCommunicationDTO.getQueueTimes())){
                        queueTimes = string2Int(ivrCommunicationDTO.getQueueTimes());
                    }
                    callLogDTO.setQueueTimes(queueTimes);
                    callLogDTO.setCallerNo(ivrCommunicationDTO.getCaller());
                    callLogDTO.setCalledNo(ivrCommunicationDTO.getCallee());
                    callLogDTO.setCallType(Integer.parseInt(ivrCommunicationDTO.getCallType()));
                    callLogDTO.setChannelNo(0);
                    callLogService.insert(callLogDTO);
                    break;
                }
                //挂机
                case ON_HOOK:{
                    if(!String.valueOf(Constants.YES).equals(reserveData)){
                        callLogDTO.setOutTime(new Date());
                        callLogService.update(callLogDTO);
                    }
                    break;
                }
                //转人工
                case TRANSFER_TO_LABOR:{
                    if(StringUtils.equals(ivrCommunicationDTO.getReasonCode(),"0000")) {
                        CallLogDTO callLog = callLogService.selectById(ivrCommunicationDTO.getCallID());
                        if (Objects.isNull(callLog) || Objects.isNull(callLog.getFirstInQueueTime())) {
                            callLogDTO.setFirstInQueueTime(nowDate);
                        }
                        callLogDTO.setInQueueTime(nowDate);
                        callLogDTO.setOutTime(nowDate);
                        callLogService.update(callLogDTO);
                    }
                    break;
                }
                //转外线
                case TRANSFER_TO_EXTERNAL_LINE:{

                    break;
                }
                //主菜单
                case MAIN_MENU:{

                    break;
                }
                //留言
                case LEAVE_MESSAGE:{

                    break;
                }
                //转人工超时
                case TRANSFER_MANUAL_TIMEOUT:{
                    CallLogDTO callLog = callLogService.selectById(ivrCommunicationDTO.getCallID());
                    if(Objects.isNull(callLog) || Objects.isNull(callLog.getFirstInQueueTime())){
                        callLogDTO.setFirstInQueueTime(nowDate);
                    }
                    if(Objects.isNull(callLog) || Objects.isNull(callLog.getInQueueTime())){
                        callLogDTO.setInQueueTime(nowDate);
                    }
                    //排队次数
                    Integer queueTimes = 1;
                    if(Objects.nonNull(callLog) && Objects.nonNull(callLog.getQueueTimes())){
                        queueTimes =  callLog.getQueueTimes() + 1;
                    }
                    callLogDTO.setQueueTimes(queueTimes);
                    callLogDTO.setOutTime(nowDate);
                    callLogService.update(callLogDTO);
                    break;
                }
                //转满意度
                case TRANSFER_SATISFACTION:{
                    String callId = ivrCommunicationDTO.getCallID();
                    if(StringUtils.isNotBlank(callId)) {
                        SatisfactionDTO satisfactionDTO = new SatisfactionDTO();
                        satisfactionDTO.setCallId(callId);
                        satisfactionDTO.setChoose(ivrCommunicationDTO.getReserveData());
                        satisfactionService.insert(satisfactionDTO);
                    }
                    break;
                }
                //不打断放提示音
                case PLAY_PROMPT_TONE_WITHOUT_INTERRUPTION:{

                    break;
                }
                //打断放提示音
                case INTERRUPT_AND_PLAY_PROMPT_TONE:{

                    break;
                }
                //放音收一位号
                case RECEIVE_ONE:{

                    break;
                }
                //区域选择
                case REGION_SELECTION:{
                    callLogDTO.setUnitCode(ivrCommunicationDTO.getAreaCode());
                    callLogService.update(callLogDTO);
                    break;
                }
                //欢迎词
                case WELCOMING_SPEECH:{

                    break;
                }
                //出IVR
                case IVR_OUTPUT:{
                    callLogDTO.setOutTime(nowDate);
                    callLogService.update(callLogDTO);
                    break;
                }
            }
        }
        //有按键轨迹插入
        if((StringUtils.isNotBlank(ivrCommunicationDTO.getTrack()) && !StringUtils.equals(NULL,ivrCommunicationDTO.getTrack()))
                ||(StringUtils.isNotBlank(ivrCommunicationDTO.getSceneType()) && !StringUtils.equals(NULL,ivrCommunicationDTO.getSceneType()))){
            insertCallOperationDetail(ivrCommunicationDTO);
        }

        //更新日志表信息
        //查询按键信息
        IvrDTO ivrDTO  = new IvrDTO();
        ivrDTO.setOrgId(null2String(ivrCommunicationDTO.getAreaCode()));
        ivrDTO.setKeyValue(StringUtils.isNotBlank(ivrCommunicationDTO.getTrack()) && !NULL.equals(ivrCommunicationDTO.getTrack()) ? ivrCommunicationDTO.getTrack():IVR_DEFAULT_KEY_VALUE);
        ivrDTO.setScenarioTypeCode(sceneType);
        IvrDTO selectOneResult = ivrService.selectOne(ivrDTO);
        //更新call_log表的按键信息
        if (Objects.nonNull(selectOneResult)) {
            callLogDTO.setKeyValue(selectOneResult.getKeyValue());
            callLogDTO.setIvrName(selectOneResult.getName());
            callLogDTO.setIvrScenarioId(null2String(ivrCommunicationDTO.getSceneID()));
            callLogDTO.setIvrScenarioTypeCode(sceneType);
            callLogService.update(callLogDTO);
        }
        log.info("通讯日志结果返回:{}",result);
        return result;
    }

    /**
     * 插入按键轨迹
     * @param ivrCommunicationDTO
     */
    public void insertCallOperationDetail(IVRCommunicationDTO ivrCommunicationDTO){

        CallOperationDetailDTO callOperationDetailDTO = new CallOperationDetailDTO();
        callOperationDetailDTO.setCallId(ivrCommunicationDTO.getCallID());
        callOperationDetailDTO.setUnitCode(UnitCodeUtil.getUnitCode(ivrCommunicationDTO.getAreaCode()));
        String id = UUIDUtils.getUUID();
        callOperationDetailDTO.setId(id);

        if(StringUtils.isNotBlank(ivrCommunicationDTO.getSceneType()) &&
                !StringUtils.equals(NULL,ivrCommunicationDTO.getSceneType())) {
            callOperationDetailDTO.setSceneType(getNullValue(ivrCommunicationDTO.getSceneType()));
        }

        if(StringUtils.isNotBlank(ivrCommunicationDTO.getTrack()) &&
                !StringUtils.equals(NULL,ivrCommunicationDTO.getTrack())) {
            callOperationDetailDTO.setOperationNo(ivrCommunicationDTO.getTrack());
        }
        callOperationDetailDTO.setReasonCode(getNullValue(ivrCommunicationDTO.getReasonCode()));
        callOperationDetailDTO.setReserveData(getNullValue(ivrCommunicationDTO.getReserveData()));
        callOperationDetailService.insertIvr(callOperationDetailDTO);
    }

    /**
     * 处理null字符
     * @param value
     * @return
     */
    public String getNullValue(String value){
        if(StringUtils.equals(NULL,value) || value==null){
            return null;
        }
        return value;
    }


    /**
     * 录音
     * @param ivrCommunicationDTO
     * @return
     */
    @ResponseBody
    @RequestMapping("/record/json")
    @TokenValidate
    public JSONObject recordJson(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        log.info("录音请求参数:{}",ivrCommunicationDTO);
        String recordId=ivrCommunicationDTO.getRecordID();
        String recordFileName=ivrCommunicationDTO.getRecordName();
        JSONObject result = new JSONObject();//返回结果
        RecordLogDTO recordLogDTO =new RecordLogDTO();
        //场景类型
        String requestTypeStr = null2String(ivrCommunicationDTO.getRequestType());
        Integer requestType = string2Int(requestTypeStr);
        RequestTypeEnum requestTypeEnum = RequestTypeEnum.getRequestTypeEnum(requestType);
        String callId = ivrCommunicationDTO.getCallID();
        String caller = ivrCommunicationDTO.getCaller();
        String unitCode = ivrCommunicationDTO.getAreaCode();
        if(Objects.nonNull(requestTypeEnum)) {
            switch (requestTypeEnum) {
                //获取录音文件名
                case GET_FILE_NAME:{
                    recordId = getRecordId();
                    //录音文件
                    recordFileName = recordId ;//+ Constants.RECORD_EXT;
                    result.put("recordNameOut",recordFileName);
                    result.put("recordIDOut",recordId);
                    break;
                }
                //开始录音
                case START_RECORDING:{
                    boolean isInsert=true;
                    if(StringUtils.isBlank(recordId)||StringUtils.equals(NULL,recordId)){
                        recordId = getRecordId();
                    }else {
                        isInsert=false;
                        recordLogDTO = recordLogService.selectById(recordId);
                        if(recordLogDTO==null){
                            isInsert=true;
                            recordLogDTO=new RecordLogDTO();
                        }
                    }
                    result.put("recordIDOut",recordId);
                    result.put("recordNameOut",recordFileName);
                    recordLogDTO.setId(recordId);
                    recordLogDTO.setRecordFileName(recordFileName);
                    recordLogDTO.setCallId(callId);
                    recordLogDTO.setCaller(caller);
                    recordLogDTO.setUnitCode(unitCode);
                    recordLogDTO.setRecordBeginTime(new Date());
                    //设置呼入呼出
                    recordLogDTO.setCallType(Integer.parseInt(ivrCommunicationDTO.getCallType()));
                    //场景类型
                    String sceneTypeStr = null2String(ivrCommunicationDTO.getSceneType());
                    Integer sceneType = string2Int(sceneTypeStr);
                    ScenarioTypeEnum scenarioTypeEnum = ScenarioTypeEnum.getScenarioTypeEnum(sceneType);
                    if(Objects.nonNull(scenarioTypeEnum)) {
                        switch (scenarioTypeEnum) {
                            //自动留言
                            case LEAVE_MESSAGE: {
                                recordLogDTO.setRecordType(RecordTypeEnum.AUTO_RECORD.getCode());
                                updateCallLog(callId,unitCode,caller,Boolean.TRUE);
                                break;
                            }
                            //转外线
                            case TRANSFER_TO_EXTERNAL_LINE: {
                                recordLogDTO.setRecordType(RecordTypeEnum.TRANSFER_RECORD.getCode());
                                DutyUserCallDTO dutyUserCallDTO = dutyUserCallService.selectByCallId(ivrCommunicationDTO.getCallID());
                                if(Objects.nonNull(dutyUserCallDTO)){
                                    recordLogDTO.setUserId(dutyUserCallDTO.getUserId());
                                    recordLogDTO.setUserName(dutyUserCallDTO.getUserName());
                                    recordLogDTO.setWorkNumber(dutyUserCallDTO.getWorkNumber());
                                    CallLogDTO callLogDTO = new CallLogDTO();
                                    callLogDTO.setCallId(ivrCommunicationDTO.getCallID());
                                    callLogDTO.setInQueueTime(new Date());
                                    callLogService.update(callLogDTO);
                                }
                                break;
                            }
                        }
                    }
                    if(isInsert) {
                        recordLogService.insert(recordLogDTO);
                    }else {
                        recordLogService.update(recordLogDTO);
                    }
                    break;
                }
                //录音结束
                case END_RECORDING:{
                    if(StringUtils.isNotBlank(recordId)) {
                        recordLogDTO.setId(recordId);
                        recordLogDTO.setRecordEndTime(new Date());
                        recordLogDTO.setRecordFileName(recordFileName);
                        recordLogService.update(recordLogDTO);
                        //呼转录音
                        if (TRANSFER_TO_EXTERNAL_LINE.getCode().equals(string2Int(ivrCommunicationDTO.getSceneType()))) {
                            DutyUserCallDTO dutyUserCallDTO = dutyUserCallService.selectByCallId(ivrCommunicationDTO.getCallID());
                            if (Objects.nonNull(dutyUserCallDTO)) {
                                RecordLogDTO recordLog = recordLogService.selectById(recordId);
                                if (Objects.nonNull(recordLog)) {
                                    //更新call_log表记录来电接听坐席信息
                                    updateCallLog(dutyUserCallDTO, ivrCommunicationDTO.getCallID(), recordLog.getRecordBeginTime());
                                }
                            }
                        }
                        //自动留言
                        else if(ScenarioTypeEnum.LEAVE_MESSAGE.getCode().equals(string2Int(ivrCommunicationDTO.getSceneType()))){
                            updateCallLog(callId,unitCode,caller,Boolean.FALSE);
                        }
                    }
                    result.put("recordIDOut",StringUtils.isBlank(recordId)?NULL:recordId);
                    result.put("recordNameOut",StringUtils.isBlank(recordFileName)?NULL:recordFileName);
                    break;
                }
            }
        }
        //默认为普通用户
        log.info("录音结果返回:{}",result);
        return result;
    }


    /**
     * 值班电话
     * @param ivrCommunicationDTO
     * @return
     */
    @ResponseBody
    @RequestMapping("/dial/json")
    @TokenValidate
    public JSONObject dial(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        log.info("值班电话请求参数:{}",ivrCommunicationDTO);

        JSONObject result = new JSONObject();//返回结果
        String unitCode = ivrCommunicationDTO.getAreaCode();

        String callId = ivrCommunicationDTO.getCallID();
        String sRequestType = ivrCommunicationDTO.getRequestType();
        Integer requestType = string2Int(sRequestType);

        //场景类型
        String sceneTypeStr = null2String(ivrCommunicationDTO.getSceneType());
        Integer sceneType = string2Int(sceneTypeStr);
        ScenarioTypeEnum scenarioTypeEnum = ScenarioTypeEnum.getScenarioTypeEnum(sceneType);
        if(Objects.nonNull(scenarioTypeEnum)) {
            switch (scenarioTypeEnum) {
                //转人工
                case TRANSFER_TO_LABOR: {
                    result.put("dialType", "0");
                    break;
                }
                //转外线
                case TRANSFER_TO_EXTERNAL_LINE:
                case TRANSFER_TO_EXTERNAL_AI: {
                    result.put("dialType", "1");
                    break;
                }
            }
        }

        //默认返回null
        result.put("dialCallerOut", NULL);
        result.put("dialCalleeOut", NULL);
        //开始呼叫直接返回
        if(DialRequestTypeEnum.START_CALL.getCode().equals(requestType)){
            log.info("值班电话，开始呼叫结果返回:{}",result);
            return result;
        }

        //呼叫结束
        if(DialRequestTypeEnum.END_CALL.getCode().equals(requestType)){
            log.info("值班电话，呼叫结束结果返回:{}",result);

            DutyUserCallDTO dutyUserCallDTO = dutyUserCallService.selectByCallId(ivrCommunicationDTO.getCallID());
            if(Objects.nonNull(dutyUserCallDTO)){
                //根据原因码取名称，呼叫结果更新到表中
                dutyUserCallDTO.setReasonCode(ivrCommunicationDTO.getReasonCode());
                IVRReasonCodeEnum ivrReasonCodeEnum = IVRReasonCodeEnum.getIVRReasonCodeEnum(ivrCommunicationDTO.getReasonCode());
                if(Objects.nonNull(ivrReasonCodeEnum)){
                    dutyUserCallDTO.setReasonName(ivrReasonCodeEnum.getName());
                }
                dutyUserCallService.update(dutyUserCallDTO);
            }

            //呼叫结束释放锁定用户
            DutyUserDTO dutyUser = new DutyUserDTO();
            dutyUser.setCallId(ivrCommunicationDTO.getCallID());
            dutyUser.setIsLock(WhetherEnum.NO.getCode());
            dutyUserService.updateByCallId(dutyUser);

            return result;
        }

        //取未锁定的值班信息
        DutyUserDTO dutyUserDTO = dutyUserService.getDutyUser(unitCode,callId,WhetherEnum.NO.getCode());
        String phone = "";
        if(Objects.nonNull(dutyUserDTO)){
            //出局号码
            String callOutPrefix = paramSetService.getParamValue(ParamEnum.TX_CALL_OUT_PREFIX.getCode(), unitCode);
            phone = callOutPrefix + dutyUserDTO.getPhone();

            OrgDTO orgDTO = orgService.selectById(ivrCommunicationDTO.getAreaCode());
            result.put("dialCallerOut", ivrCommunicationDTO.getCallee());//呼出主叫
            if(Objects.nonNull(orgDTO)&&StringUtils.isNotBlank(orgDTO.getPhone())) {
                result.put("dialCallerOut", orgDTO.getPhone());//呼出主叫
            }
            result.put("dialCalleeOut", phone);//呼出被叫
        }
        log.info("值班电话，获取主被叫结果返回:{}",result);
        return result;
    }

    /**
     * 呼坐席分机播放录音
     * @param ivrCommunicationDTO
     * @return
     */
    @ResponseBody
    @RequestMapping("/playRecord/json")
    @TokenValidate
    public JSONObject playRecord(@RequestBody IVRCommunicationDTO ivrCommunicationDTO){
        //log.info("呼坐席分机播放录音请求参数:{}",ivrCommunicationDTO);
        //处理到期无效的记录
        //返回结果
        JSONObject result = new JSONObject();
        result.put("businessIDOut", NULL);
        result.put("callerOut", NULL);
        result.put("calleeOut", NULL);
        result.put("areaCodeOut", NULL);
        result.put("recordPathOut",NULL);

        String strRequestType = ivrCommunicationDTO.getRequestType();
        Integer requestType = string2Int(strRequestType);
        if(PlayRecordTypeEnum.START_RECORD.getCode().equals(requestType)){

            //log.info("呼坐席分机播放录音，开始放音结果返回:{}",ivrCommunicationDTO);
            return result;
        }

        if(PlayRecordTypeEnum.END_RECORD.getCode().equals(requestType)){
            PlayRecordDTO playRecord = new PlayRecordDTO();
            playRecord.setRecordId(ivrCommunicationDTO.getBusinessID());
            playRecord.setState(PlayRecordTypeEnum.END_RECORD.getCode());
            playRecordService.update(playRecord);

            //log.info("呼坐席分机播放录音，放音结束结果返回:{}",ivrCommunicationDTO);
            return result;
        }

        //根据业务号查询
        String areaCode = ivrCommunicationDTO.getAreaCode();
        PlayRecordDTO playRecordDTO = playRecordService.selectOne(areaCode);
        if(Objects.isNull(playRecordDTO)){
            //log.info("呼坐席分机播放录音，获取录音结果返回:{}",ivrCommunicationDTO);
            return result;
        }
        String ivrCode = paramSetService.getParamValue(ParamEnum.TX_IVR_CODE.getCode(), areaCode);
        //正常输出
        result.put("businessIDOut", playRecordDTO.getRecordId());
        result.put("callerOut",ivrCode);
        result.put("calleeOut", playRecordDTO.getExtensionNum());
        result.put("areaCodeOut", playRecordDTO.getOrgId());
        result.put("recordPathOut",playRecordDTO.getRecordPath());
        log.info("呼坐席分机播放录音结果返回:{}",result);
        return result;
    }


    /**
     * 生成录音文件ID
     *
     * @return
     */
    private String getRecordId(){

        String dateStr = DateUtils.format(new Date(), DateConstant.PURE_DATE);
        String seqName = Constants.RECORD_LOG_SEQ_PREFIX + dateStr;
        String seqNo = orderSeqService.getSeq(seqName,6);
        String recordId = dateStr + seqNo;

        return recordId;
    }

    /**
     * 转外线成功接听后，记录接听坐席信息
     *
     * @param dutyUserCallDTO 值班人员呼叫数据
     * @param callId 呼叫流水号
     * @param recordBeginTime 开始录音时间，开始录音时间为坐席接通时间
     */
    private void updateCallLog(DutyUserCallDTO dutyUserCallDTO,String callId,Date recordBeginTime){
        CallLogDTO callLogDTO = new CallLogDTO();
        callLogDTO.setCallId(callId);
        callLogDTO.setUserId(dutyUserCallDTO.getUserId());
        callLogDTO.setUserName(dutyUserCallDTO.getUserName());
        callLogDTO.setWorkNumber(dutyUserCallDTO.getWorkNumber());
        callLogDTO.setInSeatUnitCode(dutyUserCallDTO.getUserOrgId());
        callLogDTO.setRingTime(recordBeginTime);
        callLogDTO.setInSeatTime(recordBeginTime);

        callLogService.update2(callLogDTO);
    }


    /**
     * 根据录音记录业务转换业务类型
     * @param recordBusinessCode
     * @return
     */
    private Integer getBusinessTypeCode(Integer recordBusinessCode){

        RecordBusinessEnum recordBusinessEnum = RecordBusinessEnum.getRecordBusinessEnum(recordBusinessCode);

        Integer businessType = null;
        if(Objects.nonNull(recordBusinessEnum)){
            switch (recordBusinessEnum){
                case CONSULT:{
                    businessType = BusinessTypeEnum.CONSULT.getCode();
                    break;
                }
                case QUERY:{
                    businessType = BusinessTypeEnum.QUERY.getCode();
                    break;
                }
                case COMPLAIN:{
                    businessType = BusinessTypeEnum.COMPLAIN.getCode();
                    break;
                }
                case SUGGESTION:{
                    businessType = BusinessTypeEnum.SUGGESTION.getCode();
                    break;
                }
                default:{
                    businessType = null;
                    break;
                }
            }
        }
        return businessType;
    }

    /**
     * 自动留言结束录音，是否计入呼损更新call_log
     *
     * @param callId 呼叫流水号
     * @param unitCode 机构编码
     * @param caller 来电号码
     * @param isStartRecord 是否开始录音
     */
    private void updateCallLog(String callId,String unitCode,String caller,Boolean isStartRecord){

        //来电录音留言是否计入呼损记录
        String sCallingRecordIncludedCallLoss = paramSetService.getParamValue(ParamEnum.TX_CALLING_RECORD_INCLUDED_CALL_LOSS.getCode(), unitCode);
        Integer callingRecordIncludedCallLoss = string2Int(sCallingRecordIncludedCallLoss);

        CallLogDTO callLogDTO = new CallLogDTO();
        callLogDTO.setCallId(callId);
        callLogDTO.setIsRecord(WhetherEnum.YES.getCode());
        //来电留言不计入呼损,且当前时间为坐席上班时间，更新坐席时间振铃时间和坐席接听时间
        if(WhetherEnum.NO.getCode().equals(callingRecordIncludedCallLoss)){

            //查询是否节假日
            String today = DateUtils.nowDate();

            //坐席工作时间
            if(isWorkTime(unitCode)){

                callLogDTO.setOutTime(new Date());

                Date now = new Date();

                //开始录音，更新坐席接通时间
                if(isStartRecord){
                    callLogDTO.setRingTime(now);
                    callLogDTO.setInSeatTime(now);
                }

                //当前呼叫流水号呼叫记录
                CallLogDTO current = callLogService.selectById(callId);
                if(Objects.nonNull(current)){
                    if(Objects.isNull(current.getFirstInQueueTime())){
                        callLogDTO.setFirstInQueueTime(now);
                    }
                    if(Objects.isNull(current.getInQueueTime())){
                        callLogDTO.setInQueueTime(now);
                    }
                }

                //录音留言是否计入呼损标记
                callLogDTO.setIsIncludedCallLoss(WhetherEnum.NO.getCode());

                // 查询当天来电记录是否有呼损记录，如果有，将当天来电标记为呼损的记录，
                // 自动去掉呼损标记，标识为接听
                CallLogDTO param = new CallLogDTO();
                param.setStartTime(today);
                param.setEndTime(today);
                param.setCallerNo(caller);
                param.setIsLossCall(Constants.YES);
                param.setExcludeCallId(callId);

                List<CallLogDTO> list = callLogService.selectList(param);

                if(Objects.nonNull(list) && !list.isEmpty()){
                    for(CallLogDTO callLog : list){
                        CallLogDTO updateDTO = new CallLogDTO();

                        updateDTO.setCallId(callLog.getCallId());
                        updateDTO.setIsLossCall(WhetherEnum.NO.getCode());
                        updateDTO.setIsRingLossCall(WhetherEnum.NO.getCode());
                        updateDTO.setRingLossCallCode(0);

                        //开始录音，更新坐席接通时间
                        if(isStartRecord){
                            if(Objects.isNull(callLog.getFirstInQueueTime())){
                                updateDTO.setFirstInQueueTime(now);
                            }
                            if(Objects.isNull(callLog.getInQueueTime())){
                                updateDTO.setInQueueTime(now);
                            }
                            updateDTO.setRingTime(now);
                            updateDTO.setInSeatTime(now);
                        }

                        updateDTO.setIsIncludedCallLoss(WhetherEnum.NO.getCode());

                        callLogService.update2(updateDTO);
                    }
                }
            }
        }
        callLogService.update2(callLogDTO);
    }

    /**
     * 是否工作时间
     * @param areaCode
     * @return
     */
    private Boolean isWorkTime(String areaCode){

        String unitCode = UnitCodeUtil.getUnitCode(areaCode);
        //查询是否节假日
        String today = DateUtils.format(new Date(),"yyyy-M-d");
        Integer holidayCount = holidayService.count(unitCode,today);
        //是节假日，返回非工作时间
        if(Objects.nonNull(holidayCount) && holidayCount >= 1){
            return Boolean.FALSE;
        }
        //查询是否工作时间
        Integer workTimeCount = workTimeService.count(unitCode);

        //非工作时间
        if(Objects.isNull(workTimeCount) || workTimeCount == 0){
            return Boolean.FALSE;
        }

        return Boolean.TRUE;
    }

    /**
     * AI状态取AI场景
     * @param AIStatus AI状态
     * @param unitCode 机构代码
     * @return
     */
    private String getCallDataAI(String AIStatus,String unitCode,String defaultCallData){
        if(StringUtils.isBlank(AIStatus) || StringUtils.isBlank(unitCode)){
            return defaultCallData;
        }
        //AI场景
        String AIScene = paramSetService.getParamValue(ParamEnum.TX_AI_SCENE.getCode(),unitCode);
        if(StringUtils.isBlank(AIScene)){
            return defaultCallData;
        }
        AIStatusEnum aiStatusEnum = AIStatusEnum.getAIStatusEnum(AIStatus);
        if(Objects.nonNull(aiStatusEnum)){
            switch (aiStatusEnum){
                case OPEN:
                    return AIScene;
                case WORK_TIME_OPEN:
                    if(isWorkTime(unitCode)){
                        return AIScene;
                    }
                    break;
                case NON_WORK_TIME_OPEN:
                    if(!isWorkTime(unitCode)){
                        return AIScene;
                    }
                    break;
            }
        }
        return defaultCallData;
    }
}
